package com.xique.door.project.miniprogram.biz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.xique.common.core.domain.R;
import com.xique.common.core.utils.OrikaUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.bean.dao.BuildHouseUserDAO;
import com.xique.door.bean.domain.*;
import com.xique.door.bean.request.AccessDevice.HouseSearchDeviceRequest;
import com.xique.door.bean.search.AreaBuildingHouseSearch;
import com.xique.door.bean.search.build.*;
import com.xique.door.bean.vo.area.AreaBuildingHouseVo;
import com.xique.door.biz.service.IBuildHouseUserBizService;
import com.xique.door.command.IDeviceUserCommandService;
import com.xique.door.constant.HouseClaimConstant;
import com.xique.door.constant.UserConstant;
import com.xique.door.device.freeview.constant.CommandStatus;
import com.xique.door.project.miniprogram.bean.request.MiniAddFamilyRequest;
import com.xique.door.project.miniprogram.bean.request.MiniClaimHouseRequest;
import com.xique.door.project.miniprogram.bean.request.MiniDelFamilyRequest;
import com.xique.door.project.miniprogram.bean.request.MiniImageRequuest;
import com.xique.door.project.miniprogram.bean.vo.*;
import com.xique.door.project.miniprogram.biz.service.IMiniHouseBizService;
import com.xique.door.service.*;
import com.xique.system.api.RemoteSystemProjectService;
import com.xique.system.api.dto.SystemProjectDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shd
 * @create 2022/4/18 14:56
 */
@Service
@Slf4j
public class MiniHouseBizServiceImpl implements IMiniHouseBizService {

    @Autowired
    private IBuildAreaService areaService;

    @Autowired
    private IBuildBuildingService buildingService;

    @Autowired
    private IBuildHouseService houseService;

    @Autowired
    private IHouseClaimService houseClaimService;

    @Autowired
    private IBaseUserService baseUserService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IBuildHouseUserService houseUserService;

    @Autowired
    private IAccessDeviceService accessDeviceService;

    @Autowired
    private IUserDeviceService userDeviceService;

    @Autowired
    private IDeviceUserCommandService deviceUserCommandService;

    @Autowired
    private RemoteSystemProjectService projectService;

    @Autowired
    private IBuildHouseUserBizService houseUserBizService;

    @Autowired
    private IUserAndBaseUserBizService userAndBaseUserBizService;

    @Override
    public AjaxResult getAreaList(Long projectId) {

        AreaListSearch search = new AreaListSearch();
        search.setParkId(projectId);
        List<BuildAreaV1> list = areaService.selectAreaListV1(search);
        Map<String, Object> map = new HashMap<>(1);
        if (list.size() > 0) {
            List<MiniAreaListVO> vos = OrikaUtil.converts(list, MiniAreaListVO.class, Collections.singletonMap("areaName", "name"));
            map.put("list", vos);
        }
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult getBuildingList(Long areaId) {

        BuildingListSearch search = new BuildingListSearch();
        search.setAreaId(areaId);
        List<BuildBuildingV1> list = buildingService.selectBuildBuildingListV1(search);
        Map<String, Object> map = new HashMap<>(1);
        if (list.size() > 0) {
            List<MiniBuildingListVO> vos = OrikaUtil.converts(list, MiniBuildingListVO.class, Collections.singletonMap("buildingName", "name"));
            map.put("list", vos);
        }

        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult getHouseList(Long buildingId) {

        HouseListSearch search = new HouseListSearch();
        search.setBuildingId(buildingId);
        List<BuildHouseV1> list = houseService.selectHouseListV1(search);

        if (CollectionUtil.isEmpty(list)) {
            return AjaxResult.success(Collections.singletonMap("list", new ArrayList()));
        }

        List<MiniHouseListVO> vos = OrikaUtil.converts(list, MiniHouseListVO.class, Collections.singletonMap("houseName", "name"));

        Map<String, Object> map = new HashMap<>(1);
        map.put("list", vos);

        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult claimHouse(MiniClaimHouseRequest request) {

        Long baseUserId = SecurityUtils.getBaseUserId();

        HouseClaimListSearch search = new HouseClaimListSearch();
        search.setBaseUserId(baseUserId);
        search.setHouseId(request.getHouseId());
        search.setStatuses(Arrays.asList(HouseClaimConstant.Status.WAITING, HouseClaimConstant.Status.PASS));
        List<HouseClaim> list = houseClaimService.selectHouseClaimList(search);
        if (CollectionUtil.isNotEmpty(list)) {
            return AjaxResult.error("已存在待审核或者通过审核的申请，请勿重复申请");
        }

        HouseUserListSearch houseUserListSearch = new HouseUserListSearch();
        houseUserListSearch.setHouseId(request.getHouseId());
        List<BuildHouseUserV1> houseUserV1List = houseUserService.selectHouseUserListV1(houseUserListSearch);
        long ownerCount = houseUserV1List.stream().filter(v -> UserConstant.IdentityType.OWNER.equals(v.getIdentityType())).count();
        if (ownerCount > 0) {
            return AjaxResult.error("该房屋已存在业主，请勿重复申请");
        }

        HouseClaim insert = OrikaUtil.convert(request, HouseClaim.class);
        insert.setBaseUserId(baseUserId);

        BaseUserV1 user = baseUserService.getById(baseUserId);
        if (StringUtils.isNotNull(user)) {
            insert.setPhone(user.getCellphone());
            insert.setFaceKey(user.getFaceKey());
            insert.setFaceUrl(user.getFaceUrl());
        }

        boolean isSuccess = houseClaimService.save(insert);
        if (!isSuccess) {
            return AjaxResult.error("认领申请失败");
        }

        return AjaxResult.success("认领申请成功");
    }

    @Override
    public AjaxResult myHouses() {
        Long baseUserId = SecurityUtils.getBaseUserId();
        if (StringUtils.isNull(baseUserId)) {
            return AjaxResult.error("请登录");
        }
//    Long parkId = SecurityUtils.getParkId();
//    if (StringUtils.isNull(parkId)) {
//      return AjaxResult.error("请选择小区");
//    }
//    Long userId = SecurityUtils.getUserId();
//    if (StringUtils.isNull(userId)) {
//      return AjaxResult.error("您不属于该小区", Collections.singletonMap("list", new ArrayList()));
//    }

        User user = new User();
        user.setBaseUserId(baseUserId);
        List<User> listuser = userService.selectUserList(user);
        List<BuildHouseUserDAO> list = new ArrayList<>();
        listuser.forEach(item -> {
            List<BuildHouseUserDAO> buildHouseUserDAOList = houseUserService.selectBuildHouseUserByUserIdAndHouseId(item.getId(), null);
            list.addAll(buildHouseUserDAOList);
        });

        List<MiniMyHouseListVO> vos = OrikaUtil.converts(list, MiniMyHouseListVO.class);
        vos.forEach(item -> {
            item.setStatus(HouseClaimConstant.Status.PASS);
        });

        HouseClaimListSearch search = new HouseClaimListSearch();
        //search.setParkId(parkId);
        search.setBaseUserId(baseUserId);
        search.setStatuses(Arrays.asList(HouseClaimConstant.Status.WAITING, HouseClaimConstant.Status.REJECT));
        List<HouseClaim> houseClaimList = houseClaimService.selectHouseClaimList(search);
        if (CollectionUtil.isNotEmpty(houseClaimList)) {
            List<String> houseIds = houseClaimList.stream().map(v -> v.getHouseId().toString()).distinct().collect(Collectors.toList());
            AreaBuildingHouseSearch houseSearch = new AreaBuildingHouseSearch(houseIds);
            List<AreaBuildingHouseVo> areaBuildingHouseVoList = houseService.selecAreaBuildingHouseInfoByCondition(houseSearch);
            Map<String, AreaBuildingHouseVo> areaBuildingHouseVoMap = areaBuildingHouseVoList.stream().collect(Collectors.toMap(AreaBuildingHouseVo::getHouseId, v -> v));


            houseClaimList.forEach(item -> {
                AreaBuildingHouseVo areaBuildingHouseVo = areaBuildingHouseVoMap.get(item.getHouseId().toString());
                if (StringUtils.isNotNull(areaBuildingHouseVo)) {
                    MiniMyHouseListVO vo = new MiniMyHouseListVO();
                    vo.setHouseId(item.getHouseId());
                    vo.setHouseName(areaBuildingHouseVo.getHouseName());
                    vo.setBuildingName(areaBuildingHouseVo.getBuildingName());
                    vo.setAreaName(areaBuildingHouseVo.getAreaName());
                    R<SystemProjectDTO> result = projectService.getProjectInfo(item.getParkId());
                    if (R.SUCCESS == result.getCode()) {
                        SystemProjectDTO dto = result.getData();
                        vo.setCommunityName(dto.getName());
                    }
                    vo.setIdentityType(item.getIdentityType());
                    vo.setUserId(item.getUserId());
                    vo.setStatus(item.getStatus());
                    vo.setParkId(item.getParkId());
                    vos.add(vo);
                }
            });
        }

        return AjaxResult.success(Collections.singletonMap("list", vos));
    }

    @Override
    public AjaxResult myFamilys(Long houseId, Long parkId) {

        HouseUserListSearch search = new HouseUserListSearch();
        search.setHouseId(houseId);
        List<BuildHouseUserV1> list = houseUserService.selectHouseUserListV1(search);

        List<BuildHouseUserV1> userList = new ArrayList<>();
        UserV1 userV1 = userService.seleceteUserV(SecurityUtils.getBaseUserId(), parkId, houseId);

        Long userId = userV1.getId();
        String identityType = UserConstant.IdentityType.OWNER;
        for (BuildHouseUserV1 item : list) {
            if (item.getUserId().equals(userId) && !"0".equals(item.getIdentityType())) {
                userList.add(item);
                identityType = item.getIdentityType();
                break;
            }
        }
        if (CollectionUtil.isEmpty(userList)) {
            userList.addAll(list);
        }

        List<Long> userIds = userList.stream().map(BuildHouseUserV1::getUserId).distinct().collect(Collectors.toList());
        if (!userIds.contains(userId)) {
            return AjaxResult.success(Collections.singletonMap("list", new ArrayList()));
        }
        List<UserV1> userV1List = userService.listByIds(userIds);
        Map<Long, UserV1> userV1Map = userV1List.stream().collect(Collectors.toMap(UserV1::getId, v -> v));

        List<MiniMyFamilyListVO> vos = OrikaUtil.converts(userList, MiniMyFamilyListVO.class);
        String finalIdentityType = identityType;
        vos.forEach(item -> {
            item.setCanDelete(false);
            if (StringUtils.isNotNull(userV1Map.get(item.getUserId()))) {
                UserV1 user = userV1Map.get(item.getUserId());
                item.setUserName(user.getUserName());
                item.setFaceUrl(user.getFaceUrl());
                item.setPhone(user.getPhone());
                item.setGender(user.getGender());
                item.setFaceKey(user.getFaceKey());
            }
            if (finalIdentityType.equals(UserConstant.IdentityType.OWNER) && !item.getIdentityType().equals(UserConstant.IdentityType.OWNER)) {
                item.setCanDelete(true);
            }
        });

        Map<String, Object> map = new HashMap<>(2);
        map.put("list", vos);
        map.put("identity", identityType);

        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult addFamily(MiniAddFamilyRequest request) {

        R<SystemProjectDTO> systemProjectDTO = projectService.getProjectInfo(request.getParkId());

        if (systemProjectDTO.getData().getIsPropertyExamine() == null || systemProjectDTO.getData().getIsPropertyExamine().equals("N")) {
            // 判断是否超出最大入住人数
            BuildHouseV1 houseV1 = houseService.getById(request.getHouseId());
            if (!StringUtils.isNull(houseV1) && !StringUtils.isNull(houseV1.getMaxInNumber())) {
                int count = houseUserService.checkHouseUserCount(request.getHouseId());
                if (count >= houseV1.getMaxInNumber()) {
                    return AjaxResult.error("已超出该房屋最大可入住数量，请到物业修改入住人数");
                }
            }
            //用户优化
            User insert = OrikaUtil.convert(request, User.class);
            insert.setUserType(1);
            insert.setCreateUser(SecurityUtils.getBaseUserId());
            AjaxResult result = userAndBaseUserBizService.addUser(insert,"[门禁小程序添加家庭成员]");
            if (AjaxResult.isError(result)){
                return result;
            }
            User user = (User) result.get("data");

            List<BuildHouseUserDAO> houseUserDAOList = houseUserService.selectBuildHouseUserByUserIdAndHouseId(user.getId(), request.getHouseId());
                if (CollectionUtil.isNotEmpty(houseUserDAOList)) {
                    return AjaxResult.error("该用户已经绑定此房屋，无需重复添加");
                }

                BuildHouseUser houseUser = new BuildHouseUser();
                houseUser.setHouseId(houseV1.getId());
                houseUser.setBuildingId(houseV1.getBuildingId());
                houseUser.setUserId(user.getId());
                houseUser.setUserName(user.getUserName());
                houseUser.setIdentityType(user.getType());
                houseUser.setHouseName(houseV1.getHouseName());
                BuildBuildingV1 building = buildingService.getById(houseV1.getBuildingId());
                houseUser.setBuildingName(building.getBuildingName());

                houseUserService.insertBuildHouseUser(houseUser);

                HouseSearchDeviceRequest houseSearchDeviceRequest = new HouseSearchDeviceRequest();
                houseSearchDeviceRequest.setHouseId(houseV1.getId());
                List<AccessDevice> accessDevices = accessDeviceService.selectAccessDevicesByHouseIds(houseSearchDeviceRequest);
                if (CollectionUtil.isNotEmpty(accessDevices)) {
                    List<UserDevice> userDevices = new ArrayList<>();
                    for (AccessDevice accessDevice : accessDevices) {
                        UserDevice userDevice = new UserDevice();
                        userDevice.setParkId(user.getParkId());
                        userDevice.setModel(accessDevice.getModel());
                        userDevice.setUserId(user.getId());
                        userDevice.setDeviceId(accessDevice.getId());
                        userDevice.setDevSn(accessDevice.getDevSn());
                        if (StringUtils.isEmpty(accessDevice.getOnlineStatus()) || "offline".equals(accessDevice.getOnlineStatus())) {
                            userDevice.setStatus(CommandStatus.PENDING);
                        } else {
                            if (StringUtils.isNotEmpty(user.getFaceUrl())) {
                                userDevice.setStatus(CommandStatus.SEND);
                            } else {
                                userDevice.setStatus(CommandStatus.NOFACE);
                            }
                        }
                        userDevice.setCustomId(user.getCustomId());
                        userDevice.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
                        userDevices.add(userDevice);
                    }
                    int i = userDeviceService.batchInsertUserDevice(userDevices);
                    // step3: 下发
                    if (StringUtils.isNotEmpty(user.getFaceUrl())) {
                        // 照片不为空才下发
                        deviceUserCommandService.downDevicesUsers(accessDevices, Collections.singletonList(user));
                    }
                }
            return AjaxResult.success("添加人员成功");
        }else {
            return insertExamineFamily(request);
        }
    }

    /**
     * 添加家人要物业审批
     */
    public AjaxResult insertExamineFamily(MiniAddFamilyRequest request) {

        // 判断是否超出最大入住人数
        BuildHouseV1 houseV1 = houseService.getById(request.getHouseId());
        if (!StringUtils.isNull(houseV1) && !StringUtils.isNull(houseV1.getMaxInNumber())) {
            int count = houseUserService.checkHouseUserCount(request.getHouseId());
            if (count >= houseV1.getMaxInNumber()) {
                return AjaxResult.error("已超出该房屋最大可入住数量，请到物业修改入住人数");
            }
        }
        List<BaseUserV1> baseUserV1=null;
        if (StringUtils.isNotEmpty(request.getPhone())) {
            baseUserV1 = baseUserService.selectBaseUserV1ByLoginName(request.getPhone());
            if(baseUserV1.size()>1){
                log.error("当前房屋下有多个相同用户");
            }
        }
        Long baseUserId = null;
        Long userId = null;
        if (CollectionUtil.isEmpty(baseUserV1)) {
            BaseUser baseUser = new BaseUser();
            baseUser.setUserName(request.getUserName());
            baseUser.setCellphone(request.getPhone());
            baseUser.setGender(request.getGender());
            baseUser.setRemark("业主添加，物业审批");
            baseUser.setFaceKey(request.getFaceKey());
            baseUser.setFaceUrl(request.getFaceUrl());
            baseUserService.insertBaseUser(baseUser);
            baseUserId = baseUser.getId();
        } else {
            baseUserId = baseUserV1.get(0).getId();
            //修改baseuser的照片地址
            BaseUser baseUser = new BaseUser();
            baseUser.setId(baseUserId);
            baseUser.setFaceKey(request.getFaceKey());
            baseUser.setFaceUrl(request.getFaceUrl());
            baseUserService.updateBaseUser(baseUser);

            UserV1 userV1 = userService.seleceteUserV(baseUserId, request.getParkId(), request.getHouseId());
            if (userV1 != null) {
                userId = userV1.getId();
            }
        }

        BuildHouse buildHouse = houseService.selectBuildHouseById(request.getHouseId());
        BuildBuilding buildBuilding = buildingService.selectBuildBuildingById(buildHouse.getBuildingId());


        HouseClaimListSearch search = new HouseClaimListSearch();
        search.setBaseUserId(baseUserId);
        search.setHouseId(request.getHouseId());
        search.setParkId(request.getParkId());
        search.setStatuses(Arrays.asList(HouseClaimConstant.Status.WAITING, HouseClaimConstant.Status.PASS));
        List<HouseClaim> list = houseClaimService.selectHouseClaimList(search);
        if (CollectionUtil.isNotEmpty(list)) {
            return AjaxResult.error("已存在待审核或者通过审核的申请，请勿重复申请");
        }
        if (userId != null) {
            HouseUserListSearch houseUserListSearch = new HouseUserListSearch();
            houseUserListSearch.setHouseId(request.getHouseId());
            houseUserListSearch.setUserId(userId);
            List<BuildHouseUserV1> houseUserV1List = houseUserService.selectHouseUserListV1(houseUserListSearch);

            if (houseUserV1List != null && houseUserV1List.size() > 0) {
                return AjaxResult.error("该房屋已绑定这个手机号");
            }
        }

        HouseClaim insert = OrikaUtil.convert(request, HouseClaim.class);

        insert.setBaseUserId(baseUserId);
        insert.setAreaId(buildBuilding.getAreaId());
        insert.setBuildingId(buildBuilding.getId());
        BaseUserV1 user = baseUserService.getById(baseUserId);
        if (StringUtils.isNotNull(user) && StringUtils.isNotNull(user.getFaceKey()) && StringUtils.isNotNull(user.getFaceUrl())) {
            insert.setPhone(user.getCellphone());
            insert.setFaceKey(user.getFaceKey());
            insert.setFaceUrl(user.getFaceUrl());
        }

        boolean isSuccess = houseClaimService.save(insert);
        if (!isSuccess) {
            return AjaxResult.error("添加申请失败");
        }

        return AjaxResult.success("添加申请成功");
    }

    @Override
    public AjaxResult updateImge(MiniImageRequuest request) {
        User user = userService.selectUserById(request.getUserId());
        if (request.getFaceUrl().equals(user.getFaceUrl())) {
            return AjaxResult.success();
        } else {
            User update = new User();
            update.setId(user.getId());
            update.setFaceUrl(request.getFaceUrl());
            update.setFaceKey(request.getFaceKey());
            update.setUpdateUser(SecurityUtils.getBaseUserId());
            update.setUserType(1);
            userService.updateUser(update);

            user.setFaceKey(request.getFaceKey());
            user.setFaceUrl(request.getFaceUrl());

            BuildHouseV1 houseV1 = houseService.getById(request.getHouseId());
            HouseSearchDeviceRequest houseSearchDeviceRequest = new HouseSearchDeviceRequest();
            houseSearchDeviceRequest.setHouseId(houseV1.getId());
            List<AccessDevice> accessDevices = accessDeviceService.selectAccessDevicesByHouseIds(houseSearchDeviceRequest);
            if (CollectionUtil.isNotEmpty(accessDevices)) {
                deviceUserCommandService.downDevicesUsers(accessDevices, Collections.singletonList(user));
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult delFamily(MiniDelFamilyRequest request) {

        List<BuildHouseUserDAO> list = houseUserService.selectBuildHouseUserByUserIdAndHouseId(request.getUserId(), request.getHouseId());
        if (CollectionUtil.isEmpty(list)) {
            return AjaxResult.error("为找到对应的信息");
        }
        if (list.size() > 1) {
            return AjaxResult.error("此用户多次绑定到此房屋，请联系管理员处理");
        }
        BuildHouseUserDAO houseUser = list.get(0);
        if (0 == houseUser.getIdentityType()) {
            return AjaxResult.error("此用户为业主，不能删除，请联系管理员处理");
        }
        BuildHouseUser buildHouseUser = houseUserService.selectBuildHouseUserById(houseUser.getId());

        return houseUserBizService.unBindHouseV2(buildHouseUser);
    }

    private Long addBaseUser(MiniAddFamilyRequest request) {
        BaseUserV1 insert = new BaseUserV1();
        insert.setUserName(request.getUserName());
        insert.setCellphone(request.getPhone());
        insert.setGender(request.getGender());
        if (StringUtils.isNotEmpty(request.getFaceKey())) {
            insert.setFaceKey(request.getFaceKey());
        }
        if (StringUtils.isNotEmpty(request.getFaceUrl())) {
            insert.setFaceUrl(request.getFaceUrl());
        }
        boolean isSuccess = baseUserService.save(insert);
        if (!isSuccess) {
            return 0L;
        }
        return insert.getId();
    }

    @Override
    public AjaxResult getAreaBuilding(Long houseId) {
        BuildHouse house = houseService.selectBuildHouseById(houseId);
        BuildBuilding buildBuilding = buildingService.selectBuildBuildingById(house.getBuildingId());
        BuildArea buildArea = areaService.selectBuildAreaById(buildBuilding.getAreaId());
        Map<String, Object> map = new HashedMap<>();
        map.put("houseId", house.getId());
        map.put("houseName", house.getHouseName());
        map.put("buildingId", buildBuilding.getId());
        map.put("buildingName", buildBuilding.getBuildingName());
        map.put("areaId", buildArea.getId());
        map.put("areaName", buildArea.getAreaName());
        map.put("parkId", buildArea.getParkId());
        return AjaxResult.success(map);
    }
}
